package com.cleaningcloud.cld.service.impl;

import com.cleaningcloud.cld.domain.CldContract;
import com.cleaningcloud.cld.domain.CldInvoice;
import com.cleaningcloud.cld.domain.CldSettlement;
import com.cleaningcloud.cld.domain.dto.CldInvoiceDto;
import com.cleaningcloud.cld.domain.vo.CldInvoiceVo;
import com.cleaningcloud.cld.mapper.CldContractMapper;
import com.cleaningcloud.cld.mapper.CldInvoiceMapper;
import com.cleaningcloud.cld.mapper.CldSettlementMapper;
import com.cleaningcloud.cld.service.ICldInvoiceService;
import com.cleaningcloud.common.core.utils.DateUtils;
import com.cleaningcloud.common.security.utils.SecurityUtils;
import com.ibm.icu.impl.CalendarAstronomer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 发票管理Service业务层处理
 *
 * @author cleaningcloud
 * @date 2024-10-16
 */
@Service
public class CldInvoiceServiceImpl implements ICldInvoiceService {
    @Autowired
    private CldInvoiceMapper cldInvoiceMapper;

    @Autowired
    private CldContractMapper cldContractMapper;

    @Autowired
    private CldSettlementMapper cldSettlementMapper;

    /**
     * 查询发票管理
     *
     * @param invoiceId 发票管理主键
     * @return 发票管理
     */
    @Override
    public CldInvoice selectCldInvoiceByInvoiceId(Long invoiceId) {
        return cldInvoiceMapper.selectCldInvoiceByInvoiceId(invoiceId);
    }

    /**
     * 查询发票管理列表
     *
     * @param cldInvoice 发票管理
     * @return 发票管理
     */
    @Override
    public List<CldInvoiceVo> selectCldInvoiceList(CldInvoiceDto cldInvoice) {
        return cldInvoiceMapper.selectCldInvoiceList(cldInvoice);
    }


    /**
     * 查询发票管理列表
     *
     * @param cldInvoice 发票管理
     * @return 发票管理
     */
    @Override
    public List<CldInvoiceVo> selectCldInvoiceGroupRegionList(CldInvoiceDto cldInvoice) {
        return cldInvoiceMapper.selectCldInvoiceGroupRegionList(cldInvoice);
    }

    /**
     * 新增发票管理
     *
     * @param cldInvoice 发票管理
     * @return 结果
     */
    @Override
    public int insertCldInvoice(CldInvoice cldInvoice) {
        cldInvoice.setCreateTime(DateUtils.getNowDate());
        return cldInvoiceMapper.insertCldInvoice(cldInvoice);
    }

    /**
     * 修改发票管理
     *
     * @param cldInvoice 发票管理
     * @return 结果
     */
    @Override
    public int updateCldInvoice(CldInvoice cldInvoice) {
        cldInvoice.setCreateName(SecurityUtils.getUsername());
        cldInvoice.setCreateId(SecurityUtils.getUserId());
        cldInvoice.setInvoiceDate(cldInvoice.getInvoiceDate() == null ? DateUtils.getNowDate() : cldInvoice.getInvoiceDate());
        cldInvoice.setInvoiceStatus(1L);
        // 修改结算表中的结算日期
        CldSettlement cldSettlement = cldSettlementMapper.selectCldSettlementByInvoiceId(cldInvoice.getInvoiceId());
        if (cldSettlement != null) {
            cldSettlement.setSettlementDate(DateUtils.getNowDate());
            cldSettlementMapper.updateCldSettlement(cldSettlement);
        }
        return cldInvoiceMapper.updateCldInvoice(cldInvoice);
    }

    @Override
    public int invoiceReceipt(CldInvoice cldInvoice) {
        cldInvoice.setSignStatus(1L);
        return cldInvoiceMapper.updateCldInvoice(cldInvoice);
    }

    /**
     * 批量删除发票管理
     *
     * @param invoiceIds 需要删除的发票管理主键
     * @return 结果
     */
    @Override
    public int deleteCldInvoiceByInvoiceIds(Long[] invoiceIds) {
        return cldInvoiceMapper.deleteCldInvoiceByInvoiceIds(invoiceIds);
    }

    /**
     * 删除发票管理信息
     *
     * @param invoiceId 发票管理主键
     * @return 结果
     */
    @Override
    public int deleteCldInvoiceByInvoiceId(Long invoiceId) {
        return cldInvoiceMapper.deleteCldInvoiceByInvoiceId(invoiceId);
    }

    public static void main(String[] args) {
        LocalDate cDay = LocalDate.now();
        System.out.println(cDay.lengthOfMonth());
        System.out.println(cDay.getDayOfMonth());
    }

    @Override
    @Transactional
    public void calculateProjectInvoiceTask() {
        // 当前日期
        LocalDate currDate = LocalDate.now();
        // 查询履约中合同信息
        CldContract contractQuery = new CldContract();
        contractQuery.setFlag(0L);
        contractQuery.setContractStatus(1L);
        List<CldContract> cldContractList = cldContractMapper.selectCldContractList(contractQuery);
        for (CldContract contract : cldContractList) {
            // 计算合同总月份
            int contractSumMonth = DateUtils.calculateMonthDifference(contract.getStartDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), contract.getEndDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
            // 查询项目已开具发票数量
            CldInvoiceDto invoiceQuery = new CldInvoiceDto();
            invoiceQuery.setProjectId(contract.getProjectId());
            List<CldInvoiceVo> invoiceList = cldInvoiceMapper.selectCldInvoiceList(invoiceQuery);
            // 生成当月开票信息 如合同签订日期为11.1号 则12.1日定时任务计算月差为1 已开具发票数量为0
            // 如合同签订日期为11.15 则12.1日定时任务计算月差为0 已开具发票数量为0
            if (invoiceList.size() < contractSumMonth) {
                BigDecimal invoiceAmount = contract.getContractMoney().divide(BigDecimal.valueOf(contractSumMonth), 2,RoundingMode.HALF_UP);
                // 获取合同签订日期
                LocalDate cDay = contract.getStartDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                // 如为第一个月
                if(invoiceList.isEmpty()){
                    //获取合同签订日期月份总天数
                    int currMonth = cDay.lengthOfMonth();
                    //获取合同签订日期当天
                    int dayMonth = cDay.getDayOfMonth();
                    //当月总天数 - 当天数 + 1
                    int dayBetween = currMonth - dayMonth + 1;
                    // 根据签订日期 和当前日期计算相差天数
                    invoiceAmount = invoiceAmount.divide(BigDecimal.valueOf(cDay.lengthOfMonth()),8,RoundingMode.FLOOR);
                    invoiceAmount = invoiceAmount.multiply(BigDecimal.valueOf(dayBetween)).setScale(2, RoundingMode.HALF_UP);
                }

                // 服务日期
                // 如果发票数据为0 则合同签订日期 否则为上月1号
                Date serviceDate = invoiceList.size() == 0 ? contract.getStartDate() : DateUtils.toDate(DateUtils.getLastMonthYearMonth());

                // 判断当前服务月份是否已经生成
                invoiceQuery = new CldInvoiceDto();
                invoiceQuery.setProjectId(contract.getProjectId());
                invoiceQuery.setServiceDate(serviceDate);
                List<CldInvoiceVo> isList = cldInvoiceMapper.selectCldInvoiceList(invoiceQuery);
                if(isList.isEmpty()){
                    CldInvoice cldInvoice = new CldInvoice();
                    cldInvoice.setProjectId(contract.getProjectId());
                    cldInvoice.setServiceDate(serviceDate);
                    // 应开票金额 合同金额÷合同总月份=每月应开票金额
                    cldInvoice.setAnswerInvoiceAmount(invoiceAmount);
                    cldInvoice.setInvoiceYear(currDate.getYear());
                    cldInvoice.setInvoiceMonth(currDate.getMonthValue());
                    cldInvoice.setInvoiceStatus(0L);
                    cldInvoice.setSignStatus(0L);
                    cldInvoice.setFlag(0L);
                    cldInvoice.setCreateTime(DateUtils.getNowDate());
                    cldInvoiceMapper.insertCldInvoice(cldInvoice);

                    //生成结算信息
                    CldSettlement cldSettlement = new CldSettlement();
                    cldSettlement.setInvoiceId(cldInvoice.getInvoiceId());
                    cldSettlement.setCollectionStatus(0L);
                    // 计算应结算日期
                    Calendar newCalendar = Calendar.getInstance();
                    //如果服务日期月份为12月则次月为1月
                    if((serviceDate.getMonth() + 1) == 12){
                        newCalendar.set(Calendar.YEAR,serviceDate.getYear()+1900+1);
                        newCalendar.set(Calendar.MONTH,Calendar.JANUARY);
                        newCalendar.set(Calendar.DAY_OF_MONTH,15);
                    }else{
                        newCalendar.set(Calendar.YEAR,serviceDate.getYear()+1900);
                        newCalendar.set(Calendar.MONTH,serviceDate.getMonth()+1);
                        newCalendar.set(Calendar.DAY_OF_MONTH,15);
                    }
                    cldSettlement.setSettlementDate(newCalendar.getTime());
                    cldInvoice.setCreateTime(DateUtils.getNowDate());
                    cldSettlementMapper.insertCldSettlement(cldSettlement);
                }

            }
        }
    }

    @Override
    public void automaticReceiptTask() {
//        cldInvoiceMapper.invoiceAutomaticReceipt();
    }

    @Override
    public Map<String, Object> selectCldInvoiceStatistics(CldInvoiceDto cldInvoiceDto) {
        return cldInvoiceMapper.selectCldInvoiceStatistics(cldInvoiceDto);
    }
}
